package hibari.client.ui;

import hibari.client.model.ClientServices;
import hibari.client.model.Music;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

public class MusicViewer extends Composite {

	interface MusicViewerUiBinder extends UiBinder<Widget, MusicViewer> {
	}

	private static MusicViewerUiBinder uiBinder = GWT.create(MusicViewerUiBinder.class);

	private Label activeTab;

	private Map<Long, Music> cache = new HashMap<Long, Music>();

	@UiField
	protected Label composer;

	@UiField
	protected Label composerProfileTitle;

	@UiField
	protected Label composition;

	@UiField
	protected DivElement demoPlayer;

	@UiField
	protected Label descriptionTitle;

	@UiField
	protected HTML detailContent;

	@UiField
	protected ImageElement icon;

	private boolean isLoading = false;

	private LoadHandler<MusicViewer> loadHandler;

	private Music music;

	@UiField
	protected Label titleInEnglish;

	@UiField
	protected Label titleInJapanese;

	public MusicViewer() {
		initWidget(uiBinder.createAndBindUi(this));

	}

	public void init() {
		setActiveTab(this.descriptionTitle);
		hook();
	}

	private void clearUIState() {
		this.icon.setSrc("");
		this.titleInEnglish.setText("");
		this.titleInJapanese.setText("");
		this.composer.setText("");
		this.composition.setText("");
	}

	private void fireLoadFinished() {
		if (MusicViewer.this.loadHandler != null) {
			MusicViewer.this.loadHandler.loadFinished(MusicViewer.this);
		}
	}

	public Label getActiveTab() {
		return this.activeTab;
	}

	public Music getInput() {
		return this.music;
	}

	public LoadHandler<MusicViewer> getLoadHandler() {
		return this.loadHandler;
	}

	private void hook() {
		this.descriptionTitle.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				setActiveTab(MusicViewer.this.descriptionTitle);
			}
		});

		this.composerProfileTitle.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				setActiveTab(MusicViewer.this.composerProfileTitle);
			}
		});
	}

	public boolean isLoading() {
		return this.isLoading;
	}

	public void setActiveTab(Label activeTab) {
		if (this.activeTab == activeTab) {
			return;
		}
		if (this.activeTab != null) {
			this.activeTab.removeStyleName("active-detail-tab");
		}
		this.activeTab = activeTab;
		this.activeTab.addStyleName("active-detail-tab");
		updateDetailBox();
	}

	public void setLoadHandler(LoadHandler<MusicViewer> loadHandler) {
		this.loadHandler = loadHandler;
	}

	public void setMusic(Long musicId) {
		setActiveTab(this.descriptionTitle);

		Music cachedMusic = this.cache.get(musicId);
		if (cachedMusic != null) {
			setMusic(cachedMusic);
			fireLoadFinished();
			return;
		}

		this.isLoading = true;
		ClientServices.musicService.getMusic(musicId, new AsyncCallback<Music>() {
			@Override
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
			}

			@Override
			public void onSuccess(Music result) {
				if (result != null) {
					MusicViewer.this.cache.put(result.getKey(), result);
					setMusic(result);
				}

				MusicViewer.this.isLoading = false;
				fireLoadFinished();
			}

		});
	}

	private void setMusic(Music input) {
		if (this.music == input) {
			return;
		}
		this.music = input;
		update();
	}

	@UiHandler("composer")
	protected void showComposerProfile(ClickEvent e) {
		DialogBox dialogBox = new DialogBox(true);
		dialogBox.showRelativeTo(this.composer);
	}

	private void update() {
		clearUIState();
		if (this.music == null) {
			return;
		}

		this.icon.setSrc("/image?id=" + this.music.getImageId());
		this.titleInEnglish.setText(this.music.getTitleInEnglish());
		this.titleInJapanese.setText(this.music.getTitleInJapanese());
		if (Japanese.isUserJapanese()) {
			this.composer.setText(this.music.getComposerInJapanese());
			this.composition.setText(this.music.getCompositionInJapanese());
		} else {
			this.composer.setText(this.music.getComposerInEnglish());
			this.composition.setText(this.music.getCompositionInEnglish());
		}

		updateDetailBox();
		setDemoUrl(this.music.getDemoUrl());
	}

	private void updateDetailBox() {
		if (this.music == null) {
			return;
		}
		if (Japanese.isUserJapanese()) {
			if (this.activeTab == this.descriptionTitle) {
				this.detailContent.setHTML(this.music.getDescriptionInJapanese());
			} else {
				this.detailContent.setHTML(this.music.getComposerProfileInJapanese());
			}
		} else {
			if (this.activeTab == this.descriptionTitle) {
				this.detailContent.setHTML(this.music.getDescriptionInEnglish());
			} else {
				this.detailContent.setHTML(this.music.getComposerProfileInEnglish());
			}
		}

	}

	private String playerId;

	public String getPlayerId() {
		return this.playerId;
	}

	public void setPlayerId(String playerId) {
		this.playerId = playerId;
		this.demoPlayer.setId(playerId);
	}

	public native void setDemoUrl(String url) /*-{
				console.log(url);
		var playerId = this.@hibari.client.ui.MusicViewer::playerId;
		$wnd.AudioPlayer.embed(playerId, {
			soundFile : url
		});
		console.log(url);
	}-*/;
}
